##########################################
## Copyright 2012-2013 Ceruti Francesco & contributors
##
## This file is part of LiSP (Linux Show Player).
##########################################

import pickle
from os import path
from threading import Thread

from PyQt4 import QtGui, QtCore

from lisp.utils import audiowave  # @UnresolvedImport
from lisp.utils.utility import md5sum
from .timeview import QTimeLineView
from .p_actions import Pause, Play, Seek, Stop, ToSpeed, ToVolume, PAction


class Row(QtGui.QWidget):

    def __init__(self, media, timeMode, parent=None):
        super(Row, self).__init__(parent)

        self.actionsClasses = [Pause, Seek, ToVolume]
        self.actionsClasses.append(Stop if timeMode else Play)
        self.actionsClasses.sort(key=lambda o: o.ID)
        self.actionsStr = [action.ID for action in self.actionsClasses]

        self.media = media
        self.action = self.actionsClasses[0](media)

        self.hLayout = QtGui.QHBoxLayout(self)
        self.hLayout.setMargin(2)

        self.timeEdit = QtGui.QTimeEdit(self)
        self.timeEdit.setDisplayFormat('mm.ss')
        self.timeEdit.setMinimumTime(QtCore.QTime(0, 0, 0))
        self.timeEdit.setMaximumTime(QtCore.QTime(0, (media.conf['duration'] / 60000) % 60, (media.conf['duration'] / 1000) % 60))

        if(timeMode):
            def onTimeChanged(time):
                self.action.time = (time.minute() * 60 + time.second()) * 1000
            self.timeEdit.timeChanged.connect(onTimeChanged)
        else:
            self.timeEdit.setEnabled(False)

        self.hLayout.addWidget(self.timeEdit)

        self.comboBox = QtGui.QComboBox(self)
        self.comboBox.addItems(self.actionsStr)
        self.comboBox.currentIndexChanged.connect(self.onActionChanged)

        self.hLayout.addWidget(self.comboBox)

        self.settingsButton = QtGui.QPushButton('Settings', self)
        self.settingsButton.clicked.connect(lambda: self.action.showSettingsUi())
        self.settingsButton.setEnabled(self.action.hasSettingsUi)

        self.hLayout.addWidget(self.settingsButton)

    def onActionChanged(self, index):
        self.action = self.actionsClasses[index](self.media)
        time = (self.timeEdit.time().minute() * 60 + self.timeEdit.time().second()) * 1000
        self.action.time = time if time > 0 else 1
        self.settingsButton.setEnabled(self.action.hasSettingsUi)

    def setAction(self, action):
        self.timeEdit.setTime(QtCore.QTime(0, (action.time / 60000) % 60, (action.time / 1000) % 60))
        self.comboBox.setCurrentIndex(self.actionsClasses.index(action.__class__))
        self.settingsButton.setEnabled(self.action.hasSettingsUi)
        self.action = action


class ProgrammingUI(QtGui.QDialog):

    __processed = QtCore.pyqtSignal(list, list, int)

    def __init__(self, media, timeMode=True):
        super(ProgrammingUI, self).__init__()

        self.setWindowModality(QtCore.Qt.ApplicationModal)
        self.resize(500, 300)
        self.vLayout = QtGui.QVBoxLayout(self)

        if(timeMode):
            #self.setWindowState(QtCore.Qt.WindowMaximized)
            self.resize(750, 500)

            self.view = QtGui.QLabel(self)
            self.view.setMovie(QtGui.QMovie(path.abspath(path.join(path.dirname(__file__), "loading.gif"))))
            self.view.setAlignment(QtCore.Qt.AlignCenter)
            self.view.movie().start()
            self.view.movie().setSpeed(150)
            self.vLayout.addWidget(self.view)

            def showWaveform(peaks, rms, duration):
                self.vLayout.removeWidget(self.view)
                self.view.close()

                self.view = QTimeLineView(int(len(peaks) / duration), self)
                self.vLayout.insertWidget(0, self.view)

                self.view.setWaveform(peaks, rms)

            self.__processed.connect(showWaveform, QtCore.Qt.QueuedConnection)
            Thread(target=lambda: self.__processed.emit(*getWaveform(media.conf['location']))).start()

        self.timeMode = timeMode
        self.media = media
        self.rows = []

        self.hLayout = QtGui.QHBoxLayout()
        self.vLayout.addLayout(self.hLayout)

        self.vLayout.setStretch(0, 2)
        self.vLayout.setStretch(1, 3)

        self.list = QtGui.QListWidget(self)
        self.hLayout.addWidget(self.list)
        #self.list.setDragEnabled(True)
        #self.list.setDragDropMode(QtGui.QListWidget.InternalMove)

        self.vLayout2 = QtGui.QVBoxLayout()
        self.hLayout.addLayout(self.vLayout2)

        self.hLayout.setStretch(0, 5)
        self.hLayout.setStretch(1, 1)

        self.addButton = QtGui.QPushButton(self)
        self.addButton.setText("Add")
        self.vLayout2.addWidget(self.addButton)

        self.insertButton = QtGui.QPushButton(self)
        self.insertButton.setText("Insert")
        self.vLayout2.addWidget(self.insertButton)

        self.removeButton = QtGui.QPushButton(self)
        self.removeButton.setText("Remove")
        self.vLayout2.addWidget(self.removeButton)

        self.acceptButton = QtGui.QPushButton(self)
        self.acceptButton.setText("Ok")
        self.vLayout2.addWidget(self.acceptButton)

        self.rejectButton = QtGui.QPushButton(self)
        self.rejectButton.setText("Cancel")
        self.vLayout2.addWidget(self.rejectButton)

        self.addButton.clicked.connect(lambda: self.add())
        self.insertButton.clicked.connect(lambda: self.insert())
        self.removeButton.clicked.connect(self.remove)
        self.rejectButton.clicked.connect(self.reject)
        self.acceptButton.clicked.connect(self.accept)

    def insert(self, pos=-1, action=None):
        if(pos < 0):
            pos = self.list.currentRow()

        row = Row(self.media, self.timeMode)
        if(action is not None):
            row.setAction(action)
        item = QtGui.QListWidgetItem()
        item.setSizeHint(QtCore.QSize(340, 34))

        self.list.addItem(item)
        self.list.setItemWidget(item, row)

        self.rows.append(row)

    def add(self, action=None):
        self.insert(self.list.count(), action)

    def remove(self):
        self.rows.pop(self.list.currentRow())
        self.list.takeItem(self.list.currentRow())

    def getActions(self):
        return sorted([row.action for row in self.rows], key=PAction.getTime)

    def getProgramStr(self):
        program = ''
        for row in self.rows:
            program += str(row.action) + ';'
        return program[:-1]
        print(program)

    def setActions(self, program):
        for action in program:
            self.add(action)


def getWaveform(infile):
    checksum = md5sum(infile)

    if(path.exists('/tmp/' + checksum + '.dat')):
        with open('/tmp/' + checksum + '.dat', 'rb') as inp:
            peaks, rms, duration = pickle.load(inp)
    else:
        peaks, rms = audiowave.read_audio_peaks_rms(infile, 500, 80)

        info = audiowave.read_audio_info(infile)
        duration = (info["nframes"] / info["framerate"] / info["nchannels"])

        with open('/tmp/' + checksum + '.dat', 'wb') as out:
            pickle.dump((peaks, rms, duration), out)

    peaks = [QtCore.QLineF(i, 1 - peaks[i][0], i, 1 - peaks[i][1]) for i in range(len(peaks))]
    rms = [QtCore.QLineF(i, rms[i], i, -rms[i]) for i in range(len(rms))]

    return peaks, rms, duration
